﻿using BCCommon;
using BCCommon.OAEnums;
using BCCommon.OAEnums.WorkflowActive;
using BCEntity.OA.WorkflowActive.WorkflowActivityStep;
using Dapper;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCData.OA.WorkflowActivity.WorkflowActivityStep
{
    public class WorkflowActivityStepData : IWorkflowActivityStepData
    {
        private readonly IDatabaseContext databaseContext;
        private const string QUERY_EXISTS = @"SELECT 1 FROM oa_workflowactivitystep";
        private const string QUERY = @"SELECT WorkflowActivityStepId,WorkflowActivityId,Step,StepStatus,StepOrder,IsAdditionalValidationStep,AllowAssignNextValidater,CreateTime,ActiveTime,
											CompleteTime,CompleteType,TemplateCode,TemplateName,WorkflowCode,WorkflowName,TemplateStepCode,StepCode,NodeName,NodeType,StepType,ExecutorId,
											ExecutorName,ExecutorType,RejectorId,RejectorName,RejectorType,RejectedRemark,ReplyRemark,TimeConsuming,TimeConsumingSeconds,AdditionalRemark,
											ButtonShowCondition
										FROM oa_workflowactivitystep";
        public WorkflowActivityStepData(IDatabaseContext databaseContext)
        {
            this.databaseContext = databaseContext;
        }

        #region 检查工作流活动步骤是否存在
        public async Task<bool> Exists(long workflowActivityStepId)
        {
            string sql = string.Format(@"{0} WHERE WorkflowActivityStepId=?WorkflowActivityStepId", QUERY_EXISTS);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityStepId", workflowActivityStepId, DbType.Int64);
            return await this.databaseContext.Master.ExecuteScalarAsync(sql, parameters) != null;
        }
        #endregion

        #region 添加工作流活动步骤
        public async Task<WorkflowActivityStepEntity> Add(WorkflowActivityStepEntity entity)
        {
            string sql = SqlCommands.GetInsertSql("oa_workflowactivitystep", new string[] { "WorkflowActivityId","Step", "StepStatus", "StepOrder", "IsAdditionalValidationStep", "TemplateCode", "TemplateName",
                "WorkflowCode", "WorkflowName","TemplateStepCode", "StepCode", "NodeName", "NodeType", "StepType","AllowAssignNextValidater","ActiveTime","ExecutorId","ExecutorName","ExecutorType"
                ,"AdditionalRemark" });
            sql = string.Format("{0} {1} WHERE WorkflowActivityStepId=LAST_INSERT_ID();", sql, QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityId", entity.WorkflowActivityId, DbType.Int64, size: 20);
            parameters.Add("?Step", entity.Step, DbType.Int32, size: 11);
            parameters.Add("?StepStatus", entity.StepStatus.ToString(), DbType.AnsiString);
            parameters.Add("?StepOrder", entity.StepOrder, DbType.Int32, size: 11);
            parameters.Add("?IsAdditionalValidationStep", entity.IsAdditionalValidationStep, DbType.Boolean);
            parameters.Add("?TemplateCode", entity.TemplateCode?.Trim(), DbType.AnsiString, size: 50);
            parameters.Add("?TemplateName", entity.TemplateName?.Trim(), DbType.AnsiString, size: 100);
            parameters.Add("?WorkflowCode", entity.WorkflowCode?.Trim(), DbType.AnsiString, size: 50);
            parameters.Add("?WorkflowName", entity.WorkflowName?.Trim(), DbType.AnsiString, size: 100);
            parameters.Add("?TemplateStepCode", entity.TemplateStepCode?.Trim(), DbType.AnsiString, size: 50);
            parameters.Add("?StepCode", entity.StepCode?.Trim(), DbType.AnsiString, size: 50);
            parameters.Add("?NodeName", entity.NodeName?.Trim(), DbType.AnsiString, size: 50);
            parameters.Add("?NodeType", entity.NodeType.ToString(), DbType.AnsiString);
            parameters.Add("?StepType", entity.StepType.ToString(), DbType.AnsiString);
            parameters.Add("?AllowAssignNextValidater", entity.AllowAssignNextValidater, DbType.Boolean);
            parameters.Add("?ActiveTime", entity.ActiveTime, DbType.DateTime);
            parameters.Add("?ExecutorId", entity.ExecutorId, DbType.Int64, size: 20);
            parameters.Add("?ExecutorName", entity.ExecutorName, DbType.AnsiString, size: 20);
            parameters.Add("?ExecutorType", entity.ExecutorType?.ToString(), DbType.AnsiString);
            parameters.Add("?AdditionalRemark", entity.AdditionalRemark?.Trim(), DbType.AnsiString);
            return await this.databaseContext.Master.QueryFirstOrDefaultAsync<WorkflowActivityStepEntity>(sql, parameters, databaseContext.Transaction);

        }
        #endregion

        #region 修改工作流活动步骤
        public async Task<WorkflowActivityStepEntity> UpdateStepStatusToActivity(WorkflowActivityStepEntity entity)
        {
            string sql = SqlCommands.GetUpdateSql("oa_workflowactivitystep", new string[] { "StepStatus", "ActiveTime", "ExecutorId", "ExecutorName", "ExecutorType" },
                new string[] { "WorkflowActivityStepId" });
            sql = string.Format("{0} {1} WHERE WorkflowActivityStepId=?WorkflowActivityStepId;", sql, QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityStepId", entity.WorkflowActivityStepId, DbType.Int64, size: 20);
            parameters.Add("?StepStatus", OAActivityStepStatus.Active.ToString(), DbType.AnsiString);
            parameters.Add("?ActiveTime", DateTime.Now, DbType.DateTime);
            parameters.Add("?ExecutorId", entity.ExecutorId, DbType.Int64, size: 20);
            parameters.Add("?ExecutorName", entity.ExecutorName, DbType.AnsiString, size: 20);
            parameters.Add("?ExecutorType", entity.ExecutorType?.ToString(), DbType.AnsiString);
            return await this.databaseContext.Master.QueryFirstOrDefaultAsync<WorkflowActivityStepEntity>(sql, parameters, databaseContext.Transaction);
        }
        public async Task<WorkflowActivityStepEntity> UpdateStepStatusToComplete(WorkflowActivityStepEntity entity)
        {
            string sql = SqlCommands.GetUpdateSql("oa_workflowactivitystep", new string[] { "StepStatus", "CompleteTime", "CompleteType" }, new string[] { "WorkflowActivityStepId" });
            sql = string.Format("{0} {1} WHERE WorkflowActivityStepId=?WorkflowActivityStepId;", sql, QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityStepId", entity.WorkflowActivityStepId, DbType.Int64, size: 20);
            parameters.Add("?StepStatus", OAActivityStepStatus.Done.ToString(), DbType.AnsiString);
            parameters.Add("?CompleteTime", DateTime.Now, DbType.DateTime);
            parameters.Add("?CompleteType", entity.CompleteType.ToString(), DbType.AnsiString);
            return await this.databaseContext.Master.QueryFirstOrDefaultAsync<WorkflowActivityStepEntity>(sql, parameters, databaseContext.Transaction);
        }
        #endregion

        #region 修改步骤按钮显示条件
        public async Task<WorkflowActivityStepEntity> UpdateStepButtonShowCondition(WorkflowActivityStepEntity entity)
        {
            string sql = SqlCommands.GetUpdateSql("oa_workflowactivitystep", new string[] { "ButtonShowCondition" }, new string[] { "WorkflowActivityStepId" });
            sql = string.Format("{0} {1} WHERE WorkflowActivityStepId=?WorkflowActivityStepId;", sql, QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityStepId", entity.WorkflowActivityStepId, DbType.Int64, size: 20);
            parameters.Add("?ButtonShowCondition", entity.ButtonShowCondition, DbType.AnsiString, size: 500);
            return await this.databaseContext.Master.QueryFirstOrDefaultAsync<WorkflowActivityStepEntity>(sql, parameters, databaseContext.Transaction);
        }
        #endregion

        #region 删除工作流活动步骤
        public async Task<bool> Delete(long workflowActivityStepId)
        {
            string sql = @"DELETE FROM oa_workflowactivitystep WHERE WorkflowActivityStepId=?WorkflowActivityStepId";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityStepId", workflowActivityStepId, DbType.Int64);
            return await this.databaseContext.Master.ExecuteAsync(sql, parameters, databaseContext.Transaction) > 0;
        }
        #endregion

        #region 获取工作流活动步骤
        public async Task<WorkflowActivityStepEntity> GetEntity(long workflowActivityStepId)
        {
            string sql = string.Format(@"{0} WHERE WorkflowActivityStepId=?WorkflowActivityStepId", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityStepId", workflowActivityStepId, DbType.Int64);
            return await this.databaseContext.Master.QueryFirstOrDefaultAsync<WorkflowActivityStepEntity>(sql, parameters);
        }
        public async Task<WorkflowActivityStepEntity> GetActivityEntity(long workflowActivityId)
        {
            string sql = string.Format(@"{0} WHERE WorkflowActivityId=?WorkflowActivityId AND StepStatus='Active'", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityId", workflowActivityId, DbType.Int64);
            return await this.databaseContext.Master.QueryFirstOrDefaultAsync<WorkflowActivityStepEntity>(sql, parameters);
        }
        /// <summary>
        /// 检查工作流活动步骤正在进行中的步骤信息是否存在多个
        /// </summary>
        /// <param name="workflowActivityId">工作流活动Id</param>
        public async Task<bool> GetActivityStepMoreThanOne(long workflowActivityId)
        {
            string sql = string.Format(@"SELECT COUNT(1) FROM oa_workflowactivitystep WHERE WorkflowActivityId=?WorkflowActivityId AND StepStatus='Active'", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityId", workflowActivityId, DbType.Int64);
            return await this.databaseContext.Master.ExecuteScalarAsync<int>(sql, parameters) > 1;
        }
        #endregion

        #region 获取工作流活动步骤列表
        public async Task<IEnumerable<WorkflowActivityStepEntity>> GetList(string workflowCode)
        {
            string sql = string.Format(@"{0} WHERE WorkflowCode=?WorkflowCode", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowCode", workflowCode, DbType.AnsiString);
            return await this.databaseContext.Master.QueryAsync<WorkflowActivityStepEntity>(sql, parameters);
        }
        public async Task<IEnumerable<WorkflowActivityStepEntity>> GetList(long workflowActivityId)
        {
            string sql = string.Format(@"{0} WHERE WorkflowActivityId=?WorkflowActivityId", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityId", workflowActivityId, DbType.Int64);
            return await this.databaseContext.Master.QueryAsync<WorkflowActivityStepEntity>(sql, parameters);
        }
        #endregion

        #region 获取工作流活动步骤分页
        public async Task<(IEnumerable<WorkflowActivityStepEntity>, int)> Query(DateTime? start, DateTime? end, string sortName, bool? ascending, int pageIndex, int pageSize)
        {
            List<string> wheres = new List<string>();
            DynamicParameters parameters = new DynamicParameters();

            if (start.HasValue && !end.HasValue)
            {
                wheres.Add("CreateTime>=?Start");
                parameters.Add("?Start", start.Value, DbType.DateTime);
            }
            else if (!start.HasValue && end.HasValue)
            {
                wheres.Add("CreateTime<=?End");
                parameters.Add("?End", end.Value, DbType.DateTime);
            }
            else if (start.HasValue && end.HasValue)
            {
                wheres.Add("CreateTime>=?Start AND CreateTime<=?End");
                parameters.Add("?Start", start.Value, DbType.DateTime);
                parameters.Add("?End", end.Value, DbType.DateTime);
            }
            string sql = string.Format(@"{0} {1} ORDER BY {4} {5} LIMIT {2},{3}; SELECT COUNT(1) FROM oa_workflowactivitystep {1}",
                  QUERY,
                  wheres.Count > 0 ? " WHERE " + string.Join(" AND ", wheres) : "",
                  (pageIndex == 0 ? 0 : pageIndex - 1) * pageSize,
                  pageSize,
                  string.IsNullOrWhiteSpace(sortName) ? "CreateTime" : sortName,
                  ascending.HasValue && ascending.Value ? "ASC" : "DESC");
            return await this.databaseContext.QueryMultipleAsync<WorkflowActivityStepEntity, int>(sql, parameters);
        }

        #endregion

        #region 获取工作流步骤为条件步骤的活动中列表
        public async Task<IEnumerable<WorkflowActivityStepEntity>> GetWorkflowStepConditionStatusActiveList()
        {
            string sql = string.Format(@"{0} WHERE NodeType=?NodeType AND StepStatus=?StepStatus", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?NodeType", OAStepNodeType.Condition.ToString(), DbType.AnsiString);
            parameters.Add("?StepStatus", OAActivityStepStatus.Active.ToString(), DbType.AnsiString);
            return await this.databaseContext.Master.QueryAsync<WorkflowActivityStepEntity>(sql, parameters);
        }
        #endregion

        #region 获取工作流特殊表单已审批完成待处理实例
        public async Task<IDictionary<long, string>> GetWorkflowActivityStepSpecificFormDone()
        {
            string sql = @"SELECT WorkflowActivityId,SpecificTemplateKey FROM
						(
							SELECT DISTINCT(T.WorkflowActivityId) AS WorkflowActivityId,COUNT(T.WorkflowActivityId) AS Num,T.SpecificTemplateKey FROM
							(
								SELECT DISTINCT(A.WorkflowActivityId) AS WorkflowActivityId,A.ActivityStatus,B.StepStatus,C.SpecificTemplateKey 
								FROM OA_WorkflowActivity A
								INNER JOIN OA_WorkflowActivityStep B ON A.WorkflowActivityId = B.WorkflowActivityId
								INNER JOIN OA_WorkflowTemplate C ON A.TemplateCode = C.TemplateCode
								WHERE A.IsBaseWorkflow = 0 AND A.ActivityStatus = 'Ongoing'
							) T
							GROUP BY T.WorkflowActivityId
						) S
						WHERE S.Num = 1 LIMIT 1";
            return await databaseContext.Slave.QueryDictionaryAsync<long, string>(sql);
        }
        #endregion
    }
}
